import { Object3DEventMap } from "three";
import { BaseTileMap } from "../../Docs";
import { Point } from "../../Engine";
import { App } from "../../application";
import Const from "../../application/constants/Const";
import DemTile from "../../map/Tile/DemTile";

/**
 * 淹没分析
 */
export default class BloomAnalysis {
    private isOpenAnalysis: boolean;
    private intervalID;
    private currentHeight: number;
    private positionArray: Array<number>;
    // private demHeightAdjust: number;
    private bloomShape: Array<Point>;
    private demLayer: BaseTileMap;
    private loadTileEvent;
    private updateBloomEvent;
    // private loadCacheTileEvent;
    private zoomRange;

    /**
     * 淹没分析
     * @param data 淹没分析用到的参数
     * @param data.bloomShape 淹没分析多边形的数组
     * @param data.zoomRange 淹没分析在地图的哪些层级有效
     * @param data.zoomRange.minZoom 淹没分析生效的最小图层
     * @param data.zoomRange.maxZoom 淹没分析生效的最大图层
     * @example var bloomShape = [
            new GE.Point(113.51467888565323, 37.852959765389144, 0, '4326'),
            new GE.Point(113.53528514277666, 37.81418857876654, 0, '4326'),
            new GE.Point(113.56890444567925, 37.81417658619176, 0, '4326'),
            new GE.Point(113.59004807543256, 37.85374395377242, 0, '4326')
        ];
        let zoomRange = {minZoom: 16, maxZoom: 18};
        var bloomAnalysis = new GE.BloomAnalysis({bloomShape: bloomShape, zoomRange: zoomRange});
        let maxHeight = 600;
        let upSpeed = 0.1;
        bloomAnalysis.openAnalysis(maxHeight, upSpeed); //开启淹没分析
        //bloomAnalysis.closeAnalysis(); //关闭淹没分析
     */
    public constructor(data: {bloomShape: Array<Point>, zoomRange ?: {minZoom: number, maxZoom: number}}) {
        this.isOpenAnalysis = false;
        this.bloomShape = data.bloomShape;
        this.zoomRange = data.zoomRange;
        
        this.positionArray = new Array<number>();

        // this.loadCacheTileEvent = this.loadCacheTileListener.bind(this);
        this.loadTileEvent = this.loadTileListener.bind(this);
        this.updateBloomEvent = this.updateBloomHeightListener.bind(this);

        this.bloomShape.forEach(element => {
            element.toEPSGWeb();
        });
    }

    /**
     * 开启淹没分析 
     * @param addHeight 水位淹没的最大海拔高度
     * @param upSpeed 水位每秒上升的速度
     * @example let maxHeight = 600;
        let upSpeed = 0.1;
        bloomAnalysis.openAnalysis(maxHeight, upSpeed);  
     */
    public openAnalysis(addHeight: number, upSpeed: number) {
        if (this.isOpenAnalysis) { //淹没分析本来就在开着
            return;
        }
        let demData = this.getDemData();
        if (!demData) { //当前所处的底图图层没有dem数据
            return;
        }
        this.closeAnalysis();

        let maxHeight = addHeight;
        addHeight = addHeight - demData.demHeightAdjust;

        let self = this;
        for (let i = 0; i < this.bloomShape.length; i++) {
            let currentElement = this.bloomShape[i];
            this.positionArray.push(currentElement.x, currentElement.y);
        }

        if (!this.bloomShape[0].equals(this.bloomShape[this.bloomShape.length - 1])) {
            self.positionArray.push(this.bloomShape[0].x, this.bloomShape[0].y); //形成首尾相连的闭环
        }
        this.demLayer = demData.layer;
        this.currentHeight = addHeight / 2;
        this.openBloom(this.positionArray, this.currentHeight, upSpeed, maxHeight);

        this.isOpenAnalysis = true;
    }

    private openBloom(positionArray, initHeight, upSpeed, maxHeight) {
        let self = this;
        this.demLayer.children.forEach((demTile: DemTile) => {
            //为每个瓦片开启淹没分析
            demTile.openBloom(positionArray, initHeight);
        });
        
        // this.demLayer.removeEventListener('handleCacheTile', this.loadCacheTileEvent);
        this.demLayer.addEventListener('afterLoadTile' as keyof Object3DEventMap, this.loadTileEvent);
        this.demLayer.addEventListener('updateBloomHeight' as keyof Object3DEventMap, this.updateBloomEvent);

        this.intervalID = setInterval(function () {
            self.currentHeight += upSpeed;
            var event = { type: 'updateBloomHeight'};
            // @ts-ignore
            self.demLayer.dispatchEvent(event);

            if (self.currentHeight >= maxHeight) {
                clearInterval(self.intervalID);
            }
        }, 1);
    }

    /**
     * 关闭淹没分析
     * @example bloomAnalysis.closeAnalysis();
     */
    public closeAnalysis() {
        if(!this.demLayer){
            return;
        }

        this.isOpenAnalysis = false;
        this.positionArray = [];

        this.demLayer.children.forEach((demTile: DemTile) => {
            //关闭每个瓦片的淹没功能
            demTile.closeBloom();
        });
        this.demLayer.removeEventListener('updateBloomHeight' as keyof Object3DEventMap, this.updateBloomEvent);
        this.demLayer.removeEventListener('afterLoadTile' as keyof Object3DEventMap, this.loadTileEvent);
        // this.demLayer.addEventListener('handleCacheTile', this.loadCacheTileEvent);
    }

    private loadTileListener(event){
        let zoom = App.getInstance().map.zoom;
        if(zoom < this.zoomRange.minZoom || zoom > this.zoomRange.maxZoom){
            return;
        }

        let newTile: DemTile = event.message as DemTile;
        newTile.openBloom(this.positionArray, this.currentHeight);
    }

    private updateBloomHeightListener(event){
        let self = this;
        let target = event.target;
        let children = target.children;
        children.forEach((demTile: DemTile) => {
            //修改每个瓦片水位的高度
            demTile.updateBloomHeight(self.currentHeight);
        });
    }

    private loadCacheTileListener(event){
        let newTile: DemTile = event.message as DemTile;
        newTile.closeBloom();
    }

    private getDemData() { //当前所在图层是否有dem数据 
        let app = App.getInstance();
        let demData = null; //是否包含dem
        for (let i = 0; i < app.options.Map.baseLayer.length; i++) {
            if (app.options.Map.baseLayer[i].tileType == Const.tileType.demType) {
                let demHeightAdjust = app.options.Map.baseLayer[i].demHeightAdjust;
                let type = app.options.Map.baseLayer[i].tileType;
                let layer = app.map.getLayersByType(type)[0]; //dem图层只有一个图层
                demData = { layer: layer, demHeightAdjust: demHeightAdjust };
                return demData;
            }
        }
        return demData;
    }

}